package com.aat.dxfy.game.blankwhite;


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.ArrayList;

/**
 * 参数入口类
 */
public class R3Src {
	public static void main(String[] args) {
		BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
		String msg = "";
		String mymsg = "NO";
		try {
			while (true) {
				msg = br.readLine();//获得一个消息
				//处理完对方的情况，再处理自己的下一步棋的下法
				mymsg = readmsg(msg);
				System.out.println(mymsg);//输出消息
			}
		} catch (IOException e) {//获得输入失败
		}
	}

	 static int[] xSS = { -1, -1, 0, 1, 1, 1, 0, -1 }, ySS = { 0, 1, 1,1, 0, -1, -1, -1 };//方位表
	 static int WHITE = 1;// 1表示白方
	 static int BLACK = -1;// -1表示黑方
	 static int EMPTY = 0;// 0表示空
	 static int INF = 10000000,INFS=90000000;// α-β搜索算法的当前节点最后的结果的下限和上限
	 static int board[][] = new int[8][8];// 棋盘棋子
	 static ArrayList<int[]> check = new ArrayList<int[]>();// 可下棋子
	 static int myc = WHITE;// 默认为白色
	// 权值表
	 static int[][] weighttable = { { 100, -5, 10, 5, 5, 10, -5, 100 },
			{ -5, -45, 1, 1, 1, 1, -45, -5 }, { 10, 1, 3, 2, 2, 3, 1, 10 },
			{ 5, 1, 2, 1, 1, 2, 1, 5 }, { 5, 1, 2, 1, 1, 2, 1, 5 },
			{ 10, 1, 3, 2, 2, 3, 1, 10 }, { -5, -45, 1, 1, 1, 1, -45, -5 },
			{ 100, -5, 10, 5, 5, 10, -5, 100 } };
	 
	// 初始化棋盘,静态代码块初始化棋盘
	static {
		for (int i = 0; i < 8; i++) {// 棋盘初始化，0表示空，1表示白，-1表示黑
			for (int j = 0; j < 8; j++) {
				board[i][j] = EMPTY;
			}
		}
		board[4][4] = WHITE;
		board[3][3] = WHITE;
		board[4][3] = BLACK;
		board[3][4] = BLACK;
	}
	/**
	 * 入口方法
	 * @param msg
	 * @return
	 */
	 static String readmsg(String msg) {
		String mymsg = "NO";
		if (msg.equals("BLACK")) {	// 如果是BLACK，则表示是开局执黑
			myc = BLACK;
		} else if (msg.equals("WHITE")) {// 如果是WHITE，则表示是开局执白
			myc = WHITE;
			return "NO";
		} else if (msg.equals("NO")) {
			
		} else {
			int xOpp = msg.charAt(0) - '1', yOpp = msg.charAt(1) - 'A';
			judge(xOpp, yOpp, -myc, true);// 判断对方，处理棋盘
		}
		mymsg = botJudge();	// 处理完对方的情况，再处理自己的下一步棋的下法
		return mymsg;
	}

	/**
	 * 
	 * @param x 被判断位置的行坐标
	 * @param y 被判断位置的列坐标
	 * @param color 判断方颜色
	 * @param upt 表示在判断过程中是否同时进行棋盘的修改
	 * @return 合法则返回true，否则返回false
	 */
	 static boolean judge(int x, int y, int color, boolean upt) {
		return judge(x, y, color, upt, board);
	}

	/**
	 * 
	 * @param x 被判断位置的行坐标
	 * @param y  被判断位置的列坐标
	 * @param color 判断方颜色
	 * @param upt 表示在判断过程中是否同时进行棋盘的修改
	 * @param board 棋盘
	 * @return 合法则返回true，否则返回false
	 */
	 static boolean judge(int x, int y, int color, boolean upt,
			int[][] board) {
		boolean flag = false;
		if (isInBounds(x, y) && EMPTY == board[x][y]) {// 不越界且为空
			int xStep = 0, yStep = 0;
			for (int i = 0; i < 8; i++) {// 遍历八个方向，确定该位置是否合法
				xStep = xSS[i];
				yStep = ySS[i];
				if (dirjudge(x, y, color, xStep, yStep, upt, board)) {
					flag = true;
				}
			}
		}
		if (flag && upt) {// 如果合法且需要修改棋盘，则将这一点也修改
			board[x][y] = color;
		}
		return flag;
	}

	/**
	 * 
	 * @description 判断某个位置的某个方向是否能够翻转对手棋子，同时能够选择性地修改棋盘
	 * @param x
	 *            基础棋点行坐标
	 * @param y
	 *            基础棋点列坐标
	 * @param color
	 *            判断方的棋色
	 * @param xStep
	 *            行坐标在行方向上的单元增量
	 * @param yStep
	 *            列坐标在列方向上的单元增量
	 * @param upt
	 *            表示在判断过程中是否同时进行棋盘的修改
	 * @param board
	 * @return 在此方向能够翻转对手棋子则返回true，否则返回false
	 */
	 static boolean dirjudge(int x, int y, int color, int xStep,
			int yStep, boolean upt, int[][] board) {
		int xMv, yMv;
		xMv = x + xStep;
		yMv = y + yStep;
		while (true) {
			if (!isInBounds(xMv, yMv)) {// 如果越界则停止，此位置不合法
				break;
			} else if (EMPTY == board[xMv][yMv]) {// 如果为空则停止，此位置不合法
				break;
			} else if (color == board[xMv][yMv]) {// 如果同色
				if (xMv == x + xStep && yMv == y + yStep)
					break; // 如果是第一个就同色则停止，不合法
				else {
					if (upt)
						lineModify(x + xStep, y + yStep, xMv - xStep, yMv
								- yStep, color, board);
					return true;
				}
			}
			xMv += xStep;
			yMv += yStep;
		}
		return false;
	}

	/**
	 * @description 将一条线上的棋子修改为指定颜色
	 * @param xS
	 *            起始位置行坐标
	 * @param yS
	 *            起始位置列坐标
	 * @param xE
	 *            终止位置行坐标
	 * @param yE
	 *            终止位置列坐标
	 * @param color
	 *            所要修改成的颜色
	 * @param board
	 */
	 static void lineModify(int xS, int yS, int xE, int yE, int color,
			int[][] board) {// 给出要修改的起始和终止位置，以及要改成的颜色，这个函数可以完成修改一条线
		// 动态确定xMv和yMv的增量
		int xMoveUnit = xS > xE ? -1 : xS < xE ? 1 : 0;
		int yMoveUnit = yS > yE ? -1 : yS < yE ? 1 : 0;
		int xMv = xS, yMv = yS;// 起始位置为第一个要修改的位置
		while (board[xMv][yMv] != color) {// 当当前要修改的位置的颜色不是“终止颜色”时，循环继续
			board[xMv][yMv] = color;// 先把当前位置的颜色修改了
			xMv += xMoveUnit;// 位置指针移动到下一个位置
			yMv += yMoveUnit;
		}
	}

	/**
	 * 是否在界限内部
	 * @param x 纵坐标
	 * @param y 横坐标
	 * @return  true表示在内部，false表示出界
	 */
	 static boolean isInBounds(int x, int y) {
		if (x >= 0 && x < 8 && y >= 0 && y < 8) {
			return true;
		}
		return false;
	}

	/**
	 * AI判断 
	 * @info 首先判断分支，然后判断行动力，返回对应的行动方向字符串
	 * @return
	 */
	 static String botJudge() {
		String mymsg = "NO";
		int x = -1, y = -1;
		int maxValue = -INF;
		int a = -INF;//负的无穷大
		int b = INF;//正的无穷大
		check = new ArrayList<int[]>();// 可下子位置
		for (int i = 0; i < 8; i++)
			for (int j = 0; j < 8; j++)
				if (judge(i, j, myc, false)) {
					check.add(new int[] { i, j });
				}
		int branches = check.size();//当前可下边数
		for (int i = 0; i < branches; i++) {
			int[][] tmpBoard = new int[8][8];// 声明一个临时棋盘
			for (int j = 0; j < 8; j++) {
				for (int k = 0; k < 8; k++)
					tmpBoard[j][k] = board[j][k];
			}
			//改变临时棋盘
			judge(check.get(i)[0], check.get(i)[1], myc, true, tmpBoard);
			//搜索分支，根据行动力查询出权重
			int temp = dfs(-myc, INFS / 10, tmpBoard, false, a, b, myc);
			if (temp > a)//置换算法
				a = temp;
			if (temp <= maxValue)
				continue;
			maxValue = temp;
			//求出最大权重的x,y坐标,check是一个二元数组
			x = check.get(i)[0];
			y = check.get(i)[1];
		}
		if (branches != 0 && x != -1 && y != -1) {//判断下子是否合法，x=-1和y=-1的时候越界
			judge(x, y, myc, true);//改变棋盘
			mymsg = Integer.toString(x + 1) + (char) (y + 'A');//数组转换坐标
		}
		return mymsg;
	}

	/**
	 * 深度优先搜索
	 * @param color
	 *            下棋颜色
	 * @param branches
	 *            分支数
	 * @param cbs
	 *            棋盘
	 * @param stop是否跳过
	 * @param a
	 *            最小值
	 * @param b
	 *            最大值
	 * @param fa
	 *            下步的颜色
	 * @return 估值
	 */
	 static int dfs(int color, int branches, int[][] cbs,boolean stop, int a, int b, int fa) {
		if (branches == 0) {// 分支数为0 根据 公式计算 估值
			int a1 = 0;// 每个位置的权值和，权重
			for (int i = 0; i < 8; i++) {
				for (int j = 0; j < 8; j++) {
					if (cbs[i][j] == myc)
						a1 += weighttable[i][j];
					else if (cbs[i][j] == -myc) {
						a1 -= weighttable[i][j];
					}
				}
			}
			//估值形式为 value = p1*a1 + p2*a2;
			int[] bwCount = resCot(cbs);// 判断棋盘上黑白棋的数量
			int a2 = judgeStatic(cbs);//判断静态局势
			int p1 = 128/ (Math.abs(40 - bwCount[2])+1)+10;//权重
			int p2 = 128-p1;//行动力
			int ans = p1 * a1 + p2 * a2;
			return ans;
		}
		// 剪枝算法
		int min = INF;
		int max = -INF;
		//可下子数组集合
		ArrayList<int[]> check = new ArrayList<int[]>();
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				if (judge(i, j, color, false, cbs)) {
					check.add(new int[] { i, j });
				}
			}
		}
		int rear = check.size();// 可以下的棋数
		for (int i = 0; i < rear; i++) {
			int[][] tmpBoard = new int[8][8];//临时棋盘
			for (int j = 0; j < 8; j++) {
				for (int k = 0; k < 8; k++)
					tmpBoard[j][k] = cbs[j][k];
			}
			//改变临时棋盘
			judge(check.get(i)[0], check.get(i)[1], color, true, tmpBoard);
			//深度    搜索深度=当前可下边/可下边的位置数
			int temp = dfs(-color, branches / rear, tmpBoard, false, a, b,color);
			if (fa == myc) {//如果下步的颜色为我的颜色
				//b为最大值,a为最小值,Alpha-Beta 搜索
				if (color == -myc) {//判断颜色是不是对方颜色，然后进行对方剪枝
					if (temp < b) {
						if (temp <= a)
							return temp;
						b = temp;
					}
					if (temp < min)
						min = temp;
				} else {//下棋的夜色为我方颜色，进行我方剪枝
					if (color != myc)
						continue;
					if (temp > a) {
						if (temp > b)
							b = temp;
						a = temp;
					}
					if (temp > max)
						max = temp;
				}
			} else {//下棋的颜色与我方相同，我方剪枝
				if (fa != -myc)
					continue;
				if (color == myc) {
					if (temp > a) {
						if (temp >= b)
							return temp;
						a = temp;
					}
					if (temp > max)
						max = temp;
				} else {
					if (color != -myc)
						continue;
					if (temp < b) {
						if (temp < a)
							a = temp;
						b = temp;
					}
					if (temp < min) {
						min = temp;
					}
				}
			}
		}
		// 如果无棋可下
		if (rear == 0) {
			// 判断对方的棋
			if (!stop) {
				return dfs(fa, branches, cbs, true, a, b, fa);
			}
			// 无棋可下时，判断双方棋子数
			int bot_chess = 0;
			int player_chess = 0;
			for (int i = 0; i < 8; i++)
				for (int j = 0; j < 8; j++) {
					if (cbs[i][j] == myc)
						bot_chess++;
					else if (cbs[i][j] == -myc)
						player_chess++;
				}
			if (bot_chess > player_chess) {
				return INF / 10;
			} else {
				return -INF / 10;
			}
		}
		// 如果自己的棋取最大，对方棋取最小估值
		int ans;
		if (color == -myc) {
			ans = min;
		} else {
			ans = max;
		}
		return ans;
	}

	/**
	 * 判断局势<br/>
	 * 
	 * @param cbs
	 *            棋盘
	 * @return 返回局势
	 */
	 static int judgeStatic(int[][] cbs) {
		int ans = 0; // 局势
		int xStep = 0;
		int yStep = 0;
		for (int i = 0; i < 8; i++)
			for (int j = 0; j < 8; j++)
				if (cbs[i][j] == myc || cbs[i][j] == -myc)
					for (int k = 0; k < 8; k++) {// 遍历八个方向，确定该位置是否合法
						xStep = xSS[k];
						yStep = ySS[k];
						if (isInBounds(i + xStep, j + yStep)
								&& cbs[i + xStep][j + yStep] == EMPTY) {
							if (cbs[i][j] == myc) {
								ans--;
							} else {
								ans++;
							}
						}
					}
		return ans;
	}

	/**
	 * 获取当前黑白棋数
	 * @return 黑棋，白棋和空白的数组
	 */
	 static int[] resCot(int[][] bs) {
		int[] ii = { 0, 0, 0 };// 黑棋数量，白棋数量，空白位置
		for (int i = 0; i < 8; i++) {
			for (int j = 0; j < 8; j++) {
				if (bs[i][j] == BLACK) {
					ii[0]++;
				} else if (bs[i][j] == WHITE) {
					ii[1]++;
				} else {
					ii[2]++;
				}
			}
		}
		return ii;
	}
}